package com.bookmanager.www.controller;


import cn.hutool.core.date.DateUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.bookmanager.www.common.DTO.ShufflingFigureDTO;
import com.bookmanager.www.common.utils.AddBookByIsbnUtils;
import com.bookmanager.www.common.utils.RedisUtils;
import com.bookmanager.www.common.utils.Result;
import com.bookmanager.www.entity.FlBook;
import com.bookmanager.www.entity.FlBookHits;

import com.bookmanager.www.mapper.FlBookMapper;
import com.bookmanager.www.mapper.FlCategoriesMapper;
import com.bookmanager.www.service.FlBookService;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.shiro.authz.annotation.Logical;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.annotation.Resources;
import java.io.IOException;
import java.time.LocalDateTime;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Pattern;

/**
 * <p>
 * 图书表 前端控制器
 * </p>
 *
 * @author 风离
 * @since 2021-09-17
 */
@RestController
@RequestMapping("/fl-book")
@Api(tags = "图书管理")
@Slf4j
public class FlBookController {
    @Resource
    FlBookMapper flBookMapper;
    @Resource
    FlBookService flBookService;
    @Resource
    RedisUtils redisUtils;
    @Resource
    RedisTemplate redisTemplate;
    @Resource
    FlCategoriesMapper flCategoriesMapper;

    private static Pattern pattern = Pattern.compile("\\d{13}");




    @PostMapping("/addBookHits")
    @ApiOperation(value = "增加图书点击量",notes = "传入图书id即可")
    /**
     * 图书点击量增加逻辑： 如果该图书从未被点击过就新增 如果该图书被点击过就count++
     * 这里可以做成定时任务 先存入redis中 每隔一段时间再同步数据库 不用频繁读取数据库资源（待完成）
     */
    Result addBookHits(@RequestParam("bookId")String bookId)
    {


        Set<String> keySet = redisTemplate.keys("*");
        log.info(String.valueOf(keySet.size()));
        log.info(Arrays.toString(keySet.toArray()));
        if(redisTemplate.opsForValue().get(bookId)!=null)
        {
            redisTemplate.opsForValue().set(bookId,
                    (Integer)
                    redisTemplate.opsForValue().get(bookId)+1);
            return Result.succ("点击量+1","");
        }else {
            //初始化为1 redis数据默认永不过期
            redisTemplate.opsForValue().set(bookId,1);
            return Result.succ("该图书不存在于Redis中 点击量+1","");
        }

    }

    @ApiOperation("手动更新")
    @GetMapping("/updateBookHits")
    public void RedisBooksHitsData() {
        log.info("【图书点击量同步数据库】开始执行：{}", DateUtil.formatDateTime(new Date()));
        Set<Object> keySet = redisTemplate.keys("*");
        Object[] keyArr = keySet.toArray();
        log.info(Arrays.toString(keyArr));
        for(int i=0;i<keyArr.length;i++)
        {
            System.out.println("键数为："+keyArr.length);
            if(String.valueOf(keyArr[i]).length()==13)
            {
                /**
                 * 这里把缓存写入数据库
                 * 判断该图书是否之前被添加过 有就更新 无就新增
                 */
                System.out.println(keyArr[i]);
                String bookId = String.valueOf(keyArr[i]);
                FlBook flBook =flBookMapper.selectBookByISBN(bookId);
                if(redisUtils.get(bookId) instanceof Integer)
                {
                    int count = (int) redisUtils.get(bookId);
                    int classifyId= flCategoriesMapper.selectClassifyIdByCategoriesId(flBook.getCategoriesId());
                    FlBookHits hits = flBookMapper.selectHitsByBookId(bookId);
                    if(hits!=null)
                    {
                        if(hits.getHits()<=count)
                        {
                            //小于 才更新数据
                            int update = flBookMapper.updateHitsByBookId(bookId,count);
                            log.info("数据库是否更新点击量数据？"+update);
                        }

                    }else {
                        int create = flBookMapper.createHitsByBookId(flBook.getIsbn(),count,
                                LocalDateTime.now(),LocalDateTime.now(),flBook.getCategoriesId(),classifyId
                        );
                        log.info("数据库是否创建点击量数据？"+create);
                    }
                }


            }
        }
    }


    /**
     * 按照标准时间来算，每天12点 执行一次
     * 0 0 12 * * ?
     * 每隔1小时执行一次 0 0/30 9-17 * * ?
     */
    @Scheduled(cron = "0 0/30 * * * ?")
    public void synchronousRedisBooksHitsData() {
        log.info("【图书点击量同步数据库】开始执行：{}", DateUtil.formatDateTime(new Date()));
        Set<Object> keySet = redisTemplate.keys("*");
        Object[] keyArr = keySet.toArray();
        log.info(Arrays.toString(keyArr));
        for(int i=0;i<keyArr.length;i++)
        {
            if(String.valueOf(keyArr[i]).length()==13)
            {
                /**
                 * 这里把缓存写入数据库
                 * 判断该图书是否之前被添加过 有就更新 无就新增
                 */

                String bookId = String.valueOf(keyArr[i]);
                FlBook flBook =flBookMapper.selectBookByISBN(bookId);
                int count = (int) redisUtils.get(bookId);

                int classifyId= flCategoriesMapper.selectClassifyIdByCategoriesId(flBook.getCategoriesId());
                FlBookHits hits = flBookMapper.selectHitsByBookId(bookId);
                if(hits!=null)
                {
                    if(hits.getHits()<=count)
                    {
                        //小于 才更新数据
                        int update = flBookMapper.updateHitsByBookId(bookId,count);
                        log.info("数据库是否更新点击量数据？"+update);
                    }

                }else {
                    int create = flBookMapper.createHitsByBookId(flBook.getIsbn(),count,
                            LocalDateTime.now(),LocalDateTime.now(),flBook.getCategoriesId(),classifyId
                            );
                    log.info("数据库是否创建点击量数据？"+create);
                }

            }
        }
    }



    @GetMapping("/getInventory")
    @ApiOperation(value = "获取当前图书库存",notes = "判断当前图书库存是否充足")
    Result getInventory(@RequestParam("bookId")String bookId)
    {
        FlBook flBook = flBookMapper.selectBookByISBN(bookId);
        if(flBook!=null)
        {
            Integer inventory = flBook.getInventory();
            return Result.succ("当前图书库存查询成功",inventory);
        }
      return Result.fail("该图书不存在！！","");

    }

    @GetMapping("/zeroBuyBook")
    @ApiOperation(value="零元购")
    Result zeroBuyBook(@RequestParam("page")Integer page,
                       @RequestParam("pageSize")Integer pageSize)
    {
        FlBook flBook=new FlBook();
        IPage<FlBook> iPage = flBookService.selectPageExtZeroBuyBook(flBook,page,pageSize);
        return Result.succ("获取零元购图书列表",iPage);
    }


    @GetMapping("/searchBookByBookId")
    @ApiOperation(value = "通过图书id查询图书信息")
    Result searchBookByBookId(@RequestParam("bookId")String bookId)
    {
        return Result.succ("查询图书信息成功",flBookMapper.selectBookByBookId(bookId));
    }

    @PostMapping("/bulkInsertBooksByISBNs")
    @RequiresRoles(value = {"admin","superAdmin","超级管理员","商品管理员"},logical = Logical.OR)
    @RequiresPermissions(value = {"pms:product:create"},logical = Logical.OR)
    @ApiOperation(value="通过ISBN数组批量插入图书",notes="")
    Result bulkInsertBooksByISBNs(@RequestParam("ISBNs")String[] isbnList, @RequestParam("interfaceType")String interfaceType,
                                  @RequestParam("categoriesId")Integer categoriesId,
                                  @RequestParam("inventory")Integer[] inventory,
                                  @RequestParam("status")Integer[] status) throws IOException {
        AddBookByIsbnUtils add=new AddBookByIsbnUtils();
        FlBook book;
        ArrayList addBooks=new ArrayList();
        for(int i =0;i<isbnList.length;i++)
        {
            book= flBookMapper.selectBookByISBN(isbnList[i]);
            if(book!=null)
            {
                System.out.println("该ISBN已加入数据库");
                continue;
            }
            if(interfaceType.equals("1")) {
                book = add.addBookByIsbnUtils(isbnList[i], categoriesId,inventory[i],status[i]);
                if (book != null)
                {
                    addBooks.add(book);
                }

            }else if(interfaceType.equals("2")) {
                book = add.addBookByIsbnUtils3(isbnList[i],categoriesId,inventory[i],status[i]);
                addBooks.add(book);
            }else {
                return Result.fail("传入接口类型参数错误！！","");
            }
            if(book!=null)
            {
                System.out.println(book);
                int insert =  flBookService.insertBookByISBN(book.getBookId(),book.getBookUpId(),book.getStatus(),
                        book.getTitle(),book.getAuthorIntro(),book.getImg(),
                        book.getIsbn(),book.getAuthor(),book.getPrice(),book.getPages(),
                        book.getDoubanScore(),book.getDouban(),book.getPublished(),
                        book.getCategoriesId(),book.getInventory(),book.getDescribe(),
                        book.getBookPress(),book.getCreateTime(),book.getUpdateTime());
                if (insert==0)
                {
                    System.out.println("加入数据库失败！");
                    continue;
                }
            }

        }
        return Result.succ("批量添加成功！！",addBooks);
    }

    @GetMapping("getBookByISBN")
    @RequiresRoles(value = {"admin","superAdmin","超级管理员","商品管理员"},logical = Logical.OR)
    @RequiresPermissions(value = {"pms:product:read"},logical = Logical.OR)
    @ApiOperation(value = "通过ISBN查询图书信息",notes = "传String ISBN")
    Result getBookByISBN(@RequestParam("ISBN")String isbn)
    {
        FlBook flBook = flBookMapper.selectBookByISBN(isbn);
        if(flBook!=null)
        {
            return Result.succ("查询成功",flBook);
        }
        return Result.fail("查询失败,该ISBN图书未存入数据库","");
    }

    @GetMapping("shufflingFigure")
    @ApiOperation(value = "首页轮播图",notes = "直接访问即可 无需传参")
    Result shufflingFigure()
    {
//        String[] isbnList = new String[]{
//        "9787521719956","9787115562845","9787556232659","9787544270878","9787539964768"
//        };
        String[] isbnList = new String[]{
                "9787221150639","9787559449436","9787559642325","9787559439253",
                "9787559451682","9787559451743","9787559437389","9787210110170"
        };
        List list = new ArrayList();
//        ShufflingFigureDTO shufflingFigureDTO = new ShufflingFigureDTO();
        for (int i = 0; i < isbnList.length; i++) {
          ShufflingFigureDTO shufflingFigureDTO = new ShufflingFigureDTO();
          FlBook book =  flBookMapper.selectBookByISBN(isbnList[i]);
          String topImg = flBookMapper.selectTopImgByISBN(isbnList[i]);
          shufflingFigureDTO.setFlBook(book);
          shufflingFigureDTO.setTopImg(topImg);
          if(shufflingFigureDTO!=null)
          {
              list.add(shufflingFigureDTO);
          }
        }
        return Result.succ("获取轮播图信息成功",list);
    }

    @PostMapping("addBookByISBN")
    @RequiresRoles(value = {"admin","superAdmin","超级管理员","商品管理员"},logical = Logical.OR)
    @ApiOperation(value = "通过ISBN添加图书",notes = "传入ISBN String 类型 传入接口类型 1 免费接口 2 付费接口")
    Result addBookByISBN(@RequestParam("ISBN")String ISBN,@RequestParam("interfaceType")String interfaceType,
                         @RequestParam("categoriesId")Integer categoriesId,
                         @RequestParam("inventory")Integer inventory,
                         @RequestParam("status")Integer status) throws IOException {
        AddBookByIsbnUtils add=new AddBookByIsbnUtils();
        FlBook book;
        //首先查询该ISBN是否存在于数据库中 如果 存在就给前端反馈
        book= flBookMapper.selectBookByISBN(ISBN);
        if(book!=null)
        {
            return Result.fail("该图书已存入数据库 无需重复添加！！","");
        }
        if(interfaceType.equals("1"))
        {
            book = add.addBookByIsbnUtils(ISBN,categoriesId,inventory,status);
        }else if(interfaceType.equals("2")) {
            book = add.addBookByIsbnUtils2(ISBN,categoriesId);
        }else {
            return Result.fail("传入接口类型参数错误！！","");
        }

        if(book!=null)
        {
            System.out.println(book);
           int insert =  flBookService.insertBookByISBN(book.getBookId(),book.getBookUpId(),book.getStatus(),
                    book.getTitle(),book.getAuthorIntro(),book.getImg(),
                    book.getIsbn(),book.getAuthor(),book.getPrice(),
                   book.getPages(), book.getDoubanScore(), book.getDouban(), book.getPublished(), book.getCategoriesId(),book.getInventory(),book.getDescribe(),
                    book.getBookPress(),book.getCreateTime(),book.getUpdateTime());
           if (insert!=0)
           {
               return Result.succ("添加图书成功",book);
           }
           else {
               return Result.fail("添加到数据库失败！","");
           }
        }


        return Result.fail("添加图书失败","该ISBN不存在！");
    }

    @GetMapping("getAllBooks")
    @ApiOperation(value ="获取所有图书信息(这个接口被废弃了)",notes = "无需传入任何参数")
    Result getAllBooks()
    {
       List<FlBook> books =  flBookMapper.getAllBooks();
       if(books!=null)
       {
           return Result.succ("获取图书信息成功",books);
       }

        return Result.fail("获取图书信息失败~","");
    }


    @ApiOperation(value ="获取某个分类图书信息",notes = "传入类别id 当前页和页面接收数据大小")
    @GetMapping("getCategoriesBooks")
    Result getCategoriesBooks(@RequestParam("categoriesId")String categoriesId,@RequestParam("page")Integer page,
                              @RequestParam("pageSize")Integer pageSize)
    {
        if(categoriesId!=null)
        {
            log.info("当前传入的categoriesId为"+categoriesId);
            int cid = Integer.parseInt(categoriesId);
            int count = flBookMapper.getCategoriesBooks(cid).size();
            Map countMap=new HashMap();
            ArrayList arrayList =new ArrayList<Object>();
            countMap.put("count",count);
            arrayList.add(countMap);
            //查询数据库中是否存在该id 如果不存在则提示前端 存在则获取所有信息 这里改一下 做一下分页
            FlBook flBook=new FlBook();
            IPage<FlBook> iPage = flBookService.selectPageExt(flBook,page,pageSize,cid);
            arrayList.add(iPage);
            return Result.succ("获取分类图书分页成功！！",arrayList);

//           List<FlBook> categoriesBooks =  flBookMapper.getCategoriesBooks(cid);
//           if (categoriesBooks.size()==0)
//           {
//               return Result.fail("获取该分类图书信息失败","数据库中无此分类图书");
//           }else {
//               return Result.succ("获取该分类图书信息成功！",categoriesBooks);
//           }
        }
        return Result.fail("获取该分类图书信息失败","");
    }

}
